package main

import (
	"crypto/tls"
	"fmt"
	"time"
)

// 思考： config 模式和 builder 模式的区别点
// function options 模式
type Server struct {
	Addr     string
	Port     int
	Protocol string
	Timeout  time.Duration
	MaxConns int
	TLS      *tls.Config
}

type Option func(*Server)

func Protocol(p string) Option {
	return func(s *Server) {
		s.Protocol = p
	}
}

func Timeout(timeout time.Duration) Option {
	return func(s *Server) {
		s.Timeout = timeout
	}
}

func MaxConns(maxconns int) Option {
	return func(s *Server) {
		s.MaxConns = s.MaxConns
	}
}

func TLS(tls *tls.Config) Option {
	return func(s *Server) {
		s.TLS = tls
	}
}

func NewServer(add string, port int, options ...func(*Server)) (*Server, error) {
	srv := Server{
		Addr:     add,
		Port:     port,
		Protocol: "tcp",
		Timeout:  30 * time.Second,
		MaxConns: 1000,
		TLS:      nil,
	}

	for _, option := range options {
		option(&srv)
	}

	return &srv, nil
}

// 直觉式的编程
// 高度的可配置化
// 很容易维护和扩展
// 自文档
// 对于新来的人很容易上手
// 没有什么令人困惑的事（是nil 还是空）
func main() {
	s1, _ := NewServer("localhost", 1024)
	s2, _ := NewServer("localhost", 1024, Protocol("upd"))
	s3, _ := NewServer("localhost", 1024, Timeout(300*time.Second), MaxConns(1000))

	fmt.Println(s1, s2, s3)
}
